package com.xjtu.service.impl;


import com.xjtu.config.ThreadPoolComponent;
import com.xjtu.model.Topology;
import com.xjtu.service.NetworkService;
import com.xjtu.util.DockerUtil;
import com.xjtu.util.NetworkUtil;
import com.xjtu.vo.AttackRecordVo;
import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;


@Slf4j
@Service
public class NetworkServiceImpl implements NetworkService {

    // Key: containerName, Value: containerId
    private final Map<String, String> containerMap = new HashMap<>();
    private Topology currentTopology; // 保存当前加载的拓扑

    @Autowired
    private ThreadPoolComponent threadPoolComponent; // 注入全局线程池


    @Override
    public void loadTopology(String topologyFilePath) throws Exception {
        ObjectMapper mapper = new ObjectMapper();
        try {
            currentTopology = mapper.readValue(new File(topologyFilePath), Topology.class);
        } catch (JsonParseException e) {
            throw new RuntimeException("Failed to parse topology file: Invalid JSON format", e);
        } catch (IOException e) {
            throw new RuntimeException("Failed to read topology file: File not found or inaccessible", e);
        }

        // 创建容器
        containerMap.putAll(DockerUtil.createContainers(currentTopology.getNodes()));

        // 分配 IP 地址
        Map<String, String> ipAddressMap = new HashMap<>();
        for (Topology.Node node : currentTopology.getNodes()) {
            ipAddressMap.put(node.getName(), node.getIp());
        }

        // 连接容器到网络
        DockerUtil.connectContainersToNetwork(containerMap, "custom_network", ipAddressMap);
    }

    @Override
    public void clearNetwork() {
        DockerUtil.removeContainers(containerMap.values().stream().collect(Collectors.toList()));
        containerMap.clear();
        currentTopology = null; // 清空当前拓扑
    }

    @Override
    public int getAttackerCount() {
        if (currentTopology == null) {
            return 0; // 如果没有加载拓扑，返回 0
        }
        return (int) currentTopology.getNodes().stream()
                .filter(node -> "attacker".equalsIgnoreCase(node.getType()))
                .count();
    }

    @Override
    public int getServerCount() {
        if (currentTopology == null) {
            return 0; // 如果没有加载拓扑，返回 0
        }
        return (int) currentTopology.getNodes().stream()
                .filter(node -> "server".equalsIgnoreCase(node.getType()))
                .count();
    }

    @Override
    public void executeAttack(AttackRecordVo attackRecordVo) throws Exception {
        if (currentTopology == null) {
            throw new IllegalStateException("No topology loaded. Please load a topology first.");
        }
        List<String> targets = attackRecordVo.getTargets();
        List<String> attackers = attackRecordVo.getAttackers();
        int attackType = attackRecordVo.getAttackType();

        List<String> targetsIp = new ArrayList<>();
        targets.forEach(target -> {
            targetsIp.add(currentTopology.getNodes().stream()
                    .filter(node -> target.equalsIgnoreCase(node.getName()))
                    .findFirst()
                    .map(Topology.Node::getIp)
                    .orElse(null));
        });

        attackers.forEach(attacker -> {
            String containerId = containerMap.get(attacker);
            if (containerId != null) {
                for (String targetIp : targetsIp) {
                    threadPoolComponent.getExecutorService().submit(() -> {
                        try {
                            NetworkUtil.executeAttack(containerId, attackType, targetIp);
                        } catch (Exception e) {
                            log.error("Failed to execute attack from container: " + attacker, e);
                        }
                    });
                }
            } else {
                throw new IllegalArgumentException("Attacker container not found: " + attacker);
            }
        });
    }

    @Override
    public String getServerTrafficInfo(String serverName) throws Exception {
        if (currentTopology == null) {
            throw new IllegalStateException("No topology loaded. Please load a topology first.");
        }

        // 根据服务器名称获取对应的容器 ID
        String containerId = containerMap.get(serverName);
        if (containerId == null) {
            throw new IllegalArgumentException("Server not found: " + serverName);
        }

        // 使用工具类发送命令并获取流量信息
        try {
            return NetworkUtil.getTrafficInfo(containerId);
        } catch (Exception e) {
            throw new RuntimeException("Failed to get traffic info for server: " + serverName, e);
        }
    }
}
